package com.wlj.web.aspect;

import com.alibaba.fastjson.JSON;
import com.wlj.utils.StopWatchUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Aspect
@Component
public class WebLogAspect {

    private Logger log= LoggerFactory.getLogger(getClass());

    @Pointcut("execution(public * com.wlj.web.controller..*.*(..))")//切入点描述 这个是controller包的切入点
    public void controllerLog(){}//签名，可以理解成这个切入点的一个名称


    @Before("controllerLog()")
    public void logBeforeController(JoinPoint joinPoint) {
        StopWatchUtil.startWatch();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        // 记录下请求内容
        log.info("################IP : " + request.getRemoteAddr());
        Map<String, String> headerInfo = getHeadersInfo(request);
        log.info("################请求头 : " +  JSON.toJSONString(headerInfo));
        log.info("################请求method :{} URL :{} ",request.getMethod(),request.getRequestURL().toString());
        log.info("################请求参数 : " + JSON.toJSONString(joinPoint.getArgs()));

        //下面这个getSignature().getDeclaringTypeName()是获取包+类名的   然后后面的joinPoint.getSignature.getName()获取了方法名
        log.info("################控制器类方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());


    }

    @AfterReturning(returning = "returnOb", pointcut = "controllerLog()")
    public void doAfterReturning(JoinPoint joinPoint,Object returnOb) {
        Long totalTime = StopWatchUtil.getTotalTime();
        log.info("##################### 耗时ms: {} 返回值 : {}",totalTime,JSON.toJSONString(returnOb));
    }

    @AfterThrowing(pointcut = "controllerLog()", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        log.error("连接点方法为：" + methodName + ",参数为：" + args + ",异常为：" + ex);
    }

    /**
     * 获取请求头
     *
     * @param request
     * @return
     */
    public static Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
}
